package edu.gatech.ealf;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;

import edu.gatech.ealf.secretservantplaf.SecretServantLookAndFeel;

public abstract class AuxiliaryLookAndFeel extends LookAndFeel {

	private Map<JComponent, ComponentUI> activeComponentIndex = new HashMap<JComponent, ComponentUI>(100);
	
    protected UIDefaults uidefaults = null;
	
    protected boolean enabled = false;
    
	public AuxiliaryLookAndFeel(){
		
	}
	
	public void registerComponentInstallation(ComponentUI ui, JComponent component){
		activeComponentIndex.put(component, ui);
	}
	
	public void registerComponentUninstallation(ComponentUI ui, JComponent component){
		activeComponentIndex.remove(component);
	}
	
	public void install(){
        if(enabled){
            return;
        }
        enabled = true;
        UIManager.addAuxiliaryLookAndFeel(this);
        
		Map<JComponent, String> masterActiveComponentIndex = SecretServantLookAndFeel.getInstance().getActiveComponentIndex();
		for(Map.Entry<JComponent, String> componentEntry : masterActiveComponentIndex.entrySet()){
            JComponent component = componentEntry.getKey();
            if(activeComponentIndex.get(component) == null){
                String uiClassId = componentEntry.getValue();
                String fullClassName = (String) uidefaults.get(uiClassId);
                if(fullClassName != null){
                    try {
                        Class c = Class.forName(fullClassName);
                        Method createUIMethod = c.getMethod("createUI", new Class [] { JComponent.class });
                        ComponentUI componentUI = (ComponentUI) createUIMethod.invoke(null, new Object [] { component });
                        Method installUIMethod = c.getMethod("installUI", new Class [] { JComponent.class });
                        if(componentUI != null){
                            installUIMethod.invoke(componentUI, new Object [] { component });
                        }
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    } catch (SecurityException e) {
                        e.printStackTrace();
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
                
            }
        }
	}
	
	public void uninstall(){
        if(!enabled){
            return;
        }
        UIManager.removeAuxiliaryLookAndFeel(this);

        Map.Entry<JComponent, ComponentUI>[] activeComponentIndexCopy = new Map.Entry[activeComponentIndex.size()];
        activeComponentIndexCopy = activeComponentIndex.entrySet().toArray(activeComponentIndexCopy);
        for(Map.Entry entry : activeComponentIndexCopy){
            Map.Entry<JComponent, ComponentUI> activeComponentEntry = entry;
	        try {
                Class uiClass = activeComponentEntry.getValue().getClass();
                JComponent component = activeComponentEntry.getKey();
                ComponentUI componentUI = activeComponentEntry.getValue();
                Method uninstallUIMethod = uiClass.getMethod("uninstallUI", new Class [] { JComponent.class });
                uninstallUIMethod.invoke(componentUI, new Object [] { component });
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        
        }

        enabled = false;
    }

    public boolean isEnabled() {
        return enabled;
    }

}
